import { Pixijsvue } from ".";
import { elAnalysis } from "../../utils";
import Dep from "../dep";
import Resource from "../ResourceCenter";

const sharedPropertyDefinition: PropertyDescriptor = {
  enumerable: true,
  configurable: true,
};

export function setProxy(target: Pixijsvue, sourceKey: string, key: string) {
  sharedPropertyDefinition.get = function proxyGetter(this: Pixijsvue) {
    return this[sourceKey][key];
  };
  sharedPropertyDefinition.set = function proxySetter(
    this: Pixijsvue,
    val: any
  ) {
    this[sourceKey][key] = val;
  };
  Object.defineProperty(target, key, sharedPropertyDefinition);
}

export function initData(this: Pixijsvue) {
  const { data } = this.$options;
  if (data) {
    if (typeof data == "function") {
      this._data = data();
    } else {
      this._data = data;
    }
  }
  Object.keys(this._data).forEach((key) => {
    setProxy(this, "$data", key);
  });
}

export function initPlugin(this: Pixijsvue) {
  Pixijsvue.plugins.mixin.forEach((config) => {
    const hooks = ["beforeCreate", "created", "beforeMounte", "mounted"];
    hooks.forEach((hookName) => {
      if (config[hookName]) {
        this.$hook.addHooks(hookName, config[hookName]);
      }
    });
  });
}

export function initRootEle(this: Pixijsvue): void {
  const { el } = this.$options;
  this.$rootElement = elAnalysis(el);
  if (this.$rootElement == null) {
    throw new Error(`请检查是否存在${el}元素`);
  }
}

export function initWatcher(this: Pixijsvue) {
  const { computed, data, style } = this.$options;
  const depName_1 = "data";
  const depName_2 = "style";
  this.$watcher = {};
  this.$watcher[depName_1] = {};
  this.$watcher[depName_2] = {};
  if (data) {
    Object.keys(data).forEach((item: string) => {
      this.$watcher[depName_1][item] = [];
    });
  }
  if (computed) {
    Object.keys(computed).forEach((item: string) => {
      this.$watcher[depName_1][item] = [];
    });
  }
  if (style) {
    Object.keys(style).forEach((item: string) => {
      this.$watcher[depName_2][item] = [];
    });
  }
}

export function initDep(this: Pixijsvue) {
  const { data, computed } = this.$options;
  let DepHash: Record<string, boolean> = {};
  if (data) {
    Object.keys(data).forEach((key) => {
      DepHash[key] = false;
    });
  }
  if (computed) {
    Object.keys(computed).forEach((key) => {
      DepHash[key] = false;
    });
  }
  this.$dep = new Dep({
    DepHash,
  });
  this._depList.push({
    dep: this.$dep,
    watcher: (id: number, value: string, depName: string) => {
      this.$watcher[depName][value].push((val: any) => {
        this.$data[value] = val;
      });
    },
  });
}

export function initResource(this: Pixijsvue) {
  const { resource } = this.$options;
  if (resource) {
    this.$resource = new Resource(resource);
    this.$resource.init();
  }
}

export function initMethod(this: Pixijsvue) {
  const { methods } = this.$options;
  if (methods) {
    this.$methods = methods;
  }
}

export function initStyle(this: Pixijsvue) {
  const { style } = this.$options;
  if (style) {
    this.$style = style;
  }
}

export function initGlobalResource(this: Pixijsvue) {
  const { globalResource } = this.$options;
  if (globalResource) {
    this.$globalResource = globalResource;
  }
}

export function initComputed(this: Pixijsvue) {
  const { computed } = this.$options;
  const depName = "data";
  if (computed) this.$computed = { ...computed };
  Object.keys(this.$computed).forEach((value) => {
    this._depList.forEach((item) => {
      item.dep.setDependence(
        value,
        depName,
        () => {
          this.$data[value] = this.$computed[value].call(this);
        },
        this.$id
      );

      item.watcher(this.$id, value, depName);
    });
  });
}
